package com.yfp.client.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yfp.client.domain.*;
import com.yfp.client.domain.*;
import com.yfp.client.domain.dto.ActivitySignInsExchangeRecordReqDTO;
import com.yfp.client.domain.dto.VerifyCouponDTO;
import com.yfp.client.domain.vo.ActivitySignInsRulesVO;
import com.yfp.client.enums.ActivitySignInsRewardTypeEnums;
import com.yfp.client.enums.ClientCouponSourceEnums;
import com.yfp.client.mapper.ActivitySignInsClientRecordsMapper;
import com.yfp.client.mapper.ClientCouponMapper;
import com.yfp.client.service.*;
import com.yfp.client.service.*;
import com.yfp.client.util.RedisDistributedLock;
import com.yfp.client.util.RedisKey;
import com.yfp.client.util.ResponseEnum;
import com.yfp.client.util.SecurityUtils;
import com.yfp.common.core.utils.DateUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;

/**
 *
 * @description 针对表【activity_sign_ins_client_records(打卡管理-参与用户领取表)】的数据库操作Service实现
 * @createDate 2025-01-03 17:46:13
 */
@Slf4j
@Service
public class ActivitySignInsClientRecordsServiceImpl extends ServiceImpl<ActivitySignInsClientRecordsMapper, ActivitySignInsClientRecords> implements ActivitySignInsClientRecordsService {

    @Resource
    public RedisTemplate redisTemplate;
    @Resource
    private ActivitySignInsRulesService activitySignInsRulesService;
    @Resource
    private ActivitySignInsClientsService activitySignInsClientsService;
    @Resource
    private ActivitySignInsClientRecordsMapper activitySignInsClientRecordsMapper;
    @Resource
    private ClientCouponMapper clientCouponMapper;
    @Resource
    private MarCouponService marCouponService;
    @Resource
    private MarCouponPackService marCouponPackService;
    @Resource
    private MarCouponPackDetailsService marCouponPackDetailsService;
    @Resource
    private OrderComboService orderComboService;

    @Override
    public ActivitySignInsRules receiveReward(Long activitySignInsRulesId) {
        String clientId = SecurityUtils.getClientId();
        ActivitySignInsRules activitySignInsRules = activitySignInsRulesService.getById(activitySignInsRulesId);

        List<Long> clientCouponIdList = new ArrayList<>();

        if (CollUtil.contains(ActivitySignInsRewardTypeEnums.getMarCouponList(), activitySignInsRules.getRewardType())) {
            for (Long l = 0L; l < activitySignInsRules.getDistributionQuantity(); l++) {
                VerifyCouponDTO verifyCouponDTO = this.verifyCoupon(activitySignInsRules.getRewardId(), clientId, null, null);
                log.info("打卡优惠券发放,客户id{},优惠券id{},结果：{}", clientId, activitySignInsRules.getRewardId(), verifyCouponDTO.getResponseEnum().getMsg());
                if (ResponseEnum.OPERATOR_SUCCESS.getCode().equals(verifyCouponDTO.getResponseEnum().getCode())) {
                    clientCouponIdList.add(verifyCouponDTO.getClientCoupon().getId());
                }
            }
        } else if (CollUtil.contains(ActivitySignInsRewardTypeEnums.getMarCouponPackList(), activitySignInsRules.getRewardType())) {
            List<MarCouponPackDetails> marCouponPackDetails = marCouponPackDetailsService.findByCouponPackId(activitySignInsRules.getRewardId());
            MarCouponPackDetails first = CollUtil.getFirst(marCouponPackDetails);
            MarCouponPack marCouponPack = marCouponPackService.findById(first.getCouponPackId());
            if (1 == marCouponPack.getStatus()) {
                for (Long l = 0L; l < activitySignInsRules.getDistributionQuantity(); l++) {
                    for (MarCouponPackDetails marCouponPackDetail : marCouponPackDetails) {
                        for (int i = 0; i < marCouponPackDetail.getCouponCount(); i++) {
                            VerifyCouponDTO verifyCouponDTO = this.verifyCoupon(marCouponPackDetail.getCouponId(), clientId, marCouponPackDetail.getCouponPackId(), null);
                            log.info("打卡礼包优惠券发放,客户id{},优惠券id{},结果：{}", clientId, activitySignInsRules.getRewardId(), verifyCouponDTO.getResponseEnum().getMsg());
                            if (ResponseEnum.OPERATOR_SUCCESS.getCode().equals(verifyCouponDTO.getResponseEnum().getCode())) {
                                clientCouponIdList.add(verifyCouponDTO.getClientCoupon().getId());
                            }
                        }
                    }
                }
            }
        }

        if (CollUtil.isEmpty(clientCouponIdList)) {
            return null;
        }

        ActivitySignInsClientRecords activitySignInsClientRecords = new ActivitySignInsClientRecords();
        activitySignInsClientRecords.setActivitySignInsId(activitySignInsRules.getActivitySignInsId());
        activitySignInsClientRecords.setActivitySignInsRuleId(activitySignInsRules.getId());
        activitySignInsClientRecords.setClientId(SecurityUtils.getClientId());
        activitySignInsClientRecords.setRewardType(activitySignInsRules.getRewardType());
        activitySignInsClientRecords.setRewardId(activitySignInsRules.getRewardId());
        activitySignInsClientRecords.setReceiveState(1);
        activitySignInsClientRecords.setReceiveTime(DateUtil.date());
        activitySignInsClientRecords.setRemark("打卡成功");
        activitySignInsClientRecords.setCreateTime(DateUtil.date());
        activitySignInsClientRecordsMapper.insert(activitySignInsClientRecords);

        clientCouponMapper.editActivitySignInsClientRecordsId(activitySignInsClientRecords.getId(), clientCouponIdList);

        return activitySignInsRules;
    }

    @Override
    public List<ActivitySignInsClientRecords> getByClientAndId(Long activitySignInsId) {
        String clientId = SecurityUtils.getClientId();
        ActivitySignInsClientRecords activitySignInsClientRecords = new ActivitySignInsClientRecords();
        activitySignInsClientRecords.setActivitySignInsId(activitySignInsId);
        activitySignInsClientRecords.setClientId(clientId);

        return activitySignInsClientRecordsMapper.selectByReq(activitySignInsClientRecords);
    }

    @Override
    public List<ActivitySignInsRulesVO> fillIsReceive(Long activitySignInsId, List<ActivitySignInsRulesVO> activitySignInsRulesVOList) {
        List<ActivitySignInsClientRecords> claimRecordsList = this.getByClientAndId(activitySignInsId);
        List<Long> claimRecordsRuleIdList = claimRecordsList.stream().map(ActivitySignInsClientRecords::getActivitySignInsRuleId).toList();

        return activitySignInsRulesVOList.stream().map(item -> {
            ActivitySignInsRulesVO bean = BeanUtil.toBean(item, ActivitySignInsRulesVO.class);

            if (CollUtil.safeContains(claimRecordsRuleIdList, item.getId())) {
                bean.setIsReceive(1);
            } else {
                bean.setIsReceive(0);
            }
            return bean;
        }).toList();
    }

    @Override
    public Boolean canReceiveReward(Long activitySignInsId, List<ActivitySignInsRulesVO> activitySignInsRulesVOList) {
        ActivitySignInsClients activitySignInsClients = activitySignInsClientsService.getByClientAndId(activitySignInsId);
        List<ActivitySignInsRulesVO> activitySignInsRulesVOS = this.fillIsReceive(activitySignInsId, activitySignInsRulesVOList);
        ActivitySignInsRulesVO activitySignInsRulesVO = activitySignInsRulesVOS.stream().filter(item -> item.getIsReceive() == 0).min(Comparator.comparing(ActivitySignInsRulesVO::getRules, Comparator.naturalOrder())).orElse(null);
        if (Objects.isNull(activitySignInsRulesVO)) {
            return false;
        }
        return activitySignInsRulesVO.getRules() <= activitySignInsClients.getTotalSignIn();
    }

    @Override
    public Long canReceiveReward2(Long activitySignInsId, List<ActivitySignInsRules> activitySignInsRulesList) {
        ActivitySignInsClients activitySignInsClients = activitySignInsClientsService.getByClientAndId(activitySignInsId);
        List<ActivitySignInsRulesVO> activitySignInsRulesVOS = this.fillIsReceive(activitySignInsId, BeanUtil.copyToList(activitySignInsRulesList, ActivitySignInsRulesVO.class));
        ActivitySignInsRulesVO activitySignInsRulesVO = activitySignInsRulesVOS.stream().filter(item -> item.getIsReceive() == 0).min(Comparator.comparing(ActivitySignInsRulesVO::getRules, Comparator.naturalOrder())).orElse(null);
        if (Objects.isNull(activitySignInsRulesVO)) {
            return null;
        }
        if (activitySignInsRulesVO.getRules() <= activitySignInsClients.getTotalSignIn()) {
            return activitySignInsRulesVO.getId();
        } else {
            return null;
        }
    }

    @Override
    public Boolean isAllRewardsReceived(Long activitySignInsId, List<ActivitySignInsRulesVO> activitySignInsRulesVOList) {
        List<ActivitySignInsRulesVO> activitySignInsRulesVOS = this.fillIsReceive(activitySignInsId, activitySignInsRulesVOList);
        // 如果存在没有领取的奖品，则返回false
        return activitySignInsRulesVOS.stream().noneMatch(item -> item.getIsReceive() == 0);
    }

    @Override
    public List<ActivitySignInsClientRecords> exchangeRecord(ActivitySignInsExchangeRecordReqDTO exchangeRecordReqDTO) {
        LambdaQueryWrapper<ActivitySignInsClientRecords> query = Wrappers.lambdaQuery(ActivitySignInsClientRecords.class);
        query.eq(ActivitySignInsClientRecords::getActivitySignInsId, exchangeRecordReqDTO.getActivitySignInsId());
        query.eq(ActivitySignInsClientRecords::getClientId, SecurityUtils.getClientId());
        query.between(Objects.nonNull(exchangeRecordReqDTO.getStartTime()) && Objects.nonNull(exchangeRecordReqDTO.getEndTime()), ActivitySignInsClientRecords::getCreateTime, exchangeRecordReqDTO.getStartTime(), exchangeRecordReqDTO.getEndTime());

        return activitySignInsClientRecordsMapper.selectList(query);
    }

    @Override
    public VerifyCouponDTO verifyCoupon(Long couponId, String clientId, Long couponPackId, String cityName) {
        RedisDistributedLock redisDistributedLock = new RedisDistributedLock(redisTemplate, RedisKey.COUPONLOCK, 10);
        VerifyCouponDTO verifyCouponDTO = new VerifyCouponDTO();
        try {
            // 加锁
            redisDistributedLock.lock();

            MarCoupon marCoupon = marCouponService.findById(couponId);

            // 优惠券不存在
            if (null == marCoupon) {
                redisDistributedLock.unlock();
                verifyCouponDTO.setResponseEnum(ResponseEnum.COUPON_NOT_EXIST);
                return verifyCouponDTO;
            }
            if (null != cityName && !cityName.equals(marCoupon.getCityName()) && !cityName.equals("全国")) {
                redisDistributedLock.unlock();
                verifyCouponDTO.setResponseEnum(ResponseEnum.COUPON_NOT_CITY);
                return verifyCouponDTO;
            }
            // 优惠券删除或者优惠券失效
            if (marCoupon.getStatus() == 0 || marCoupon.getStatus() == 2 || marCoupon.getStatus() == 5) {
                redisDistributedLock.unlock();
                verifyCouponDTO.setResponseEnum(ResponseEnum.COUPON_LOSE_EFFICACY);
                return verifyCouponDTO;
            }

            // 优惠券剩余数量不足
            // 发放的是礼包里的券时，判断优惠券剩余数量
            if (Objects.nonNull(couponPackId)){
                if (marCoupon.getSurplusCount() == 0) {
                    redisDistributedLock.unlock();
                    verifyCouponDTO.setResponseEnum(ResponseEnum.COUPON_NOT_SURPLUS_COUNT);
                    return verifyCouponDTO;
                }
            }

            // 最大领取
            int countCoupon = clientCouponMapper.countByClientIdAndCouponId(clientId, couponId, null);
            if (countCoupon >= marCoupon.getReceiveCount()) {
                redisDistributedLock.unlock();
                verifyCouponDTO.setResponseEnum(ResponseEnum.COUPON_COUNT_EXCEED);
                return verifyCouponDTO;
            }
            if (null != marCoupon.getValidDays() && marCoupon.getValidDays() != 0) {
                // 当前日期
                LocalDate currentDate = LocalDate.now();
                // 要添加的天数
                int daysToAdd = marCoupon.getValidDays();
                // 当前日期加上指定天数
                LocalDate newDate = currentDate.plusDays(daysToAdd);
                // 获取结果日期的起始时间（00:00:00）
                LocalDateTime startOfDay = newDate.atStartOfDay();
                LocalDateTime localDateTime = startOfDay.minusSeconds(1);
                Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
                // 转换为 Date
                Date date2 = Date.from(instant);
                marCoupon.setValidStartTime(new Date());
                marCoupon.setValidEndTime(date2);
            }
            // 优惠券活动时间是否过期
            Date date = DateUtils.addDays(marCoupon.getValidEndTime(), marCoupon.getPostponeDay());
            if (date.getTime() < System.currentTimeMillis()) {
                redisDistributedLock.unlock();
                verifyCouponDTO.setResponseEnum(ResponseEnum.COUPON_OVERDUE);
                return verifyCouponDTO;
            }
            // 是否新用户
            if (marCoupon.getClientStatus() == 2) {
                Integer orderCount = orderComboService.countOrderByClientId(clientId);
                if (orderCount > 0) {
                    redisDistributedLock.unlock();
                    verifyCouponDTO.setResponseEnum(ResponseEnum.COUPON_NEW_CLIENT);
                    return verifyCouponDTO;
                }
            }

            // 发放的是礼包里的券时，扣减优惠券数量
            if (Objects.nonNull(couponPackId)){
                marCouponService.editSurplusCount(marCoupon.getId());
            }

            ClientCoupon clientCoupon = new ClientCoupon();
            BeanUtils.copyProperties(marCoupon, clientCoupon);
            clientCoupon.setClientId(clientId);
            clientCoupon.setCouponId(couponId);
            clientCoupon.setCouponPackId(couponPackId);
            clientCoupon.setSourceType(ClientCouponSourceEnums.CLOCK_REWARD.getCode());
            clientCouponMapper.insert(clientCoupon);
            log.info("clientCouponId:{}", clientCoupon.getId());

            verifyCouponDTO.setResponseEnum(ResponseEnum.OPERATOR_SUCCESS);
            verifyCouponDTO.setClientCoupon(clientCoupon);
            return verifyCouponDTO;
        } catch (Exception e) {
            e.printStackTrace();
            log.info("领券异常：{}", e.getMessage());
        } finally {
            redisDistributedLock.unlock();
        }
        verifyCouponDTO.setResponseEnum(ResponseEnum.OPERATOR_FAILUER);
        return verifyCouponDTO;
    }


}




